//
//  CubeRender.m
//  MyOpenGLESLearn_iOS
//
//  Created by Gaomingyang on 2021/4/14.
//

#import "CubeRender.h"
#import "ShaderProgram.h"


#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kCubeVertexShaderString = SHADER_STRING
(
 attribute vec3 vPosition;//顶点位置
 attribute vec4 aColor;
 uniform mat4 vMatrix; //总变换矩阵
 varying  vec4 vColor;
 void main(){
        gl_Position = vMatrix * vec4(vPosition,1);
        vColor=aColor;
    }
 );
#else

#endif

#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE
NSString *const kCubeFragmentShaderString = SHADER_STRING
(
 precision mediump float;
 varying  vec4 vColor;

 void main(){
    gl_FragColor = vColor;
 }
 );
#else

#endif

@interface CubeRender()<GLKViewDelegate>
{
    // Render
    GLuint  _program;
    GLKMatrix4  _projectionMatrix;//投影矩阵
    GLKMatrix4  _viewMatrix;//相机位置
    GLKMatrix4  _MVPMatrix;//计算变换矩阵 4
}
@property (strong, nonatomic) ShaderProgram* shaderProcessor;
@property (strong, nonatomic) EAGLContext* context;
@property (strong, nonatomic) GLKView* glkView;
@end
struct AttributeHandles
{
    GLint   vPosition;
    GLint   aColor;
};
struct UniformHandles
{
    GLuint  uProjectionMatrix;
    GLuint  uMVPMatrix;
    
};
@implementation CubeRender
{
    struct AttributeHandles _attributes;
    struct UniformHandles   _uniforms;
}
- (instancetype)initWithGLKView:(GLKView *)glkView{
    self = [super init];
    if (self) {
        [self commonInitWithGLKView:glkView];
    }
    return self;
}
-(void)commonInitWithGLKView:(GLKView *)glkView{
    [self initOpenglESWithGLKView:glkView];
}
-(void)initOpenglESWithGLKView:(GLKView *)glkView{
    self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    
    // Setup View
    self.glkView = glkView;
    self.glkView.delegate = self;
    self.glkView.context = self.context;
    self.glkView.opaque = YES;
    self.glkView.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
    self.glkView.drawableDepthFormat = GLKViewDrawableDepthFormat16;
    
    // Initialize Class Objects
    self.shaderProcessor = [[ShaderProgram alloc] init];
    [self resetupOpenGLES];
}
- (void)resetupOpenGLES
{
    [EAGLContext setCurrentContext:self.context];
    // Enable depth test
    glEnable(GL_DEPTH_TEST);
    
    CGRect screen = [self.glkView bounds];
    float aspectRatio = fabs(screen.size.width / screen.size.height);
    // Projection Matrix
    _projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(45.0), aspectRatio, 3, 20);
    /**
     float eyeX, float eyeY, float eyeZ,
     float centerX, float centerY, float centerZ,
     float upX, float upY, float upZ
     */
    _viewMatrix = GLKMatrix4MakeLookAt(5, 5, 10, 0, 0, 0, 0, 1, 0);
    _MVPMatrix = GLKMatrix4Multiply(_projectionMatrix, _viewMatrix);
    // Create the GLSL program
    _program = [self.shaderProcessor BuildProgram:[kCubeVertexShaderString cStringUsingEncoding:NSUTF8StringEncoding] with:[kCubeFragmentShaderString cStringUsingEncoding:NSUTF8StringEncoding]];

    // end create program
    glUseProgram(_program);
    
    // Extract the attribute handles
    _attributes.vPosition = glGetAttribLocation(_program, "vPosition");
    _attributes.aColor    = glGetAttribLocation(_program, "aColor");
    // Extract the uniform handles
    _uniforms.uMVPMatrix = glGetUniformLocation(_program, "vMatrix");
}
- (void)setDisplay{
    [self.glkView display];
}
# pragma mark - GLKView Delegate
- (void)update:(id)sender {
    [self.glkView display];
}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    // Clear Buffers
    glClearColor(0.05, 0.05, 0.05, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    // Enable Attributes
    glEnableVertexAttribArray(_attributes.vPosition);
    glEnableVertexAttribArray(_attributes.aColor);
    
    glUniformMatrix4fv(_uniforms.uMVPMatrix, 1, false, _MVPMatrix.m);
     float cubePositions[] = {
                -1.0f,1.0f,1.0f,    //正面左上0
                -1.0f,-1.0f,1.0f,   //正面左下1
                1.0f,-1.0f,1.0f,    //正面右下2
                1.0f,1.0f,1.0f,     //正面右上3
                -1.0f,1.0f,-1.0f,    //反面左上4
                -1.0f,-1.0f,-1.0f,   //反面左下5
                1.0f,-1.0f,-1.0f,    //反面右下6
                1.0f,1.0f,-1.0f,     //反面右上7
        };
     short index[]={
                6,7,4,6,4,5,    //后面
                6,3,7,6,2,3,    //右面
                6,5,1,6,1,2,    //下面
                0,3,2,0,2,1,    //正面
                0,1,5,0,5,4,    //左面
                0,7,3,0,4,7,    //上面
        };
    float color[] = {
                0.f,1.f,0.f,1.f,
                0.f,1.f,0.f,1.f,
                0.f,1.f,0.f,1.f,
                0.f,1.f,0.f,1.f,
                1.f,0.f,0.f,1.f,
                1.f,0.f,0.f,1.f,
                1.f,0.f,0.f,1.f,
                1.f,0.f,0.f,1.f,
        };
    glVertexAttribPointer(_attributes.vPosition, 3, GL_FLOAT, GL_FALSE, 0,cubePositions);
    
    glVertexAttribPointer(_attributes.aColor, 4, GL_FLOAT, GL_FALSE, 0, color);
//    glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, index);
    // Disable Attributes
    glDisableVertexAttribArray(_attributes.vPosition);
    glDisableVertexAttribArray(_attributes.aColor);
    
}

# pragma mark - GLKViewController Delegate

- (void)glkViewControllerUpdate:(GLKViewController *)controller
{
}
@end
